//添加样式
function addGlobalStyle(css) {
    var head, style;
    head = document.getElementsByTagName('head')[0];
    if (!head) { return; }
    style = document.createElement('style');
    style.type = 'text/css';
    style.innerHTML = css;
    head.appendChild(style);
}
//设置cookie
function setCookie(c_name, value, expiredays, path) {
	var exdate = new Date();
	exdate.setDate(exdate.getDate() + expiredays);
	document.cookie = c_name + "=" + escape(value) + ((expiredays == null) ? "" : ";expires=" + exdate.toUTCString()) + ((path == null) ? "" : ";path=" + path);
}
//生成随机字符串
function randomString(length, charslist) {
	if (!charslist)
		var chars = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXTZabcdefghiklmnopqrstuvwxyz'.split('');
	else
		var chars = charslist;
	if (!length) {
		length = Math.floor(Math.random() * chars.length);
	}

	var str = '';
	for (var i = 0; i < length; i++) {
		str += chars[Math.floor(Math.random() * chars.length)];
	}
	return str;
}
//获取链接参数
function getUrlParam(name) {
	var reg = new RegExp("(^|&)" + name + "=([^&]*)(&|$)"); //构造一个含有目标参数的正则表达式对象
	var r = window.location.search.substr(1).match(reg); //匹配目标参数
	if (r != null)
		return unescape(r[2]);
	return null; //返回参数值
}
/*
 * IE 10, Firefox 5+, Chrome 3+, Opera 12, Android 2.0+, Safari 4+, iPhone Safari
 * addStyleCompatible needed
 * If the element(s) has CSS animation "@keyframes" already, you MUST set "noStyle" to true to avoid conflict.
 * If it's not the first time you use addNodeInsertedListener for the element(s), you may also set "noStyle" to true, but it's optional.
If element(s) exists already, animationstart events will fire when css is added, the events should be canceled
 */
function addStyleCompatible(css) {
	if (typeof(GM_addStyle) != "undefined") {
		if (typeof(GM_updatingEnabled) == "undefined" || document.getElementsByTagName("head").length !== 0) {
			GM_addStyle(css); //Greasemonkey, Google Chrome, Tampermonkey
		} else {
			var timer = window.setInterval(function () { //<head> must be loaded to use GM_addStyle in Scriptish
					if (document.getElementsByTagName("head").length !== 0) {
						window.clearInterval(timer);
						GM_addStyle(css);
					}
				}, 3);
		}
	} else if (typeof(PRO_addStyle) != "undefined") { //IEPro
		PRO_addStyle(css);
	} else if (typeof(addStyle) != "undefined") { //some plugins
		addStyle(css);
	} else { //others
		var head = document.querySelector("head"),
		style;
		if (head) {
			style = document.createElement("style");
			style.type = "text/css";
			style.innerHTML = css;
			head.appendChild(style);
		}
	}
}
/*
 * addNodeInsertedListener函数
 * 本函数为未载入或已载入的对象元素添加一个肉眼看不出的、在对象元素载入时触发的动画CSS样式，并监听CSS动画事件和添加事件处理函数，以高效地达到在对象元素载入时执行事件处理函数的目的
 * @参数elCssPath：必须。对象元素的CSS路径（对象元素可以是多个，即用“.className”等来选择）；可以用伪类，这样就会在元素进行伪类相应动作（如:hover即鼠标悬停）时执行函数
 * @参数handler：可选。要添加的监听事件处理函数，函数的this关键字将指向对象元素，传递给该函数的第一个参数是事件的event对象；如果留空，则为不监听事件，只添加动画CSS样式
 * @参数executeOnce：可选。留空或false为元素载入多少次都继续监听，true为事件处理函数仅执行一次，首次执行时移除监听
 * @参数noStyle：可选。留空或false为添加动画CSS样式；true为不添加。如果对象元素已经有动画CSS样式“animation-name”、“@keyframes”了，这里需要设为true以避免冲突
 * @返回：实际绑定的事件处理函数，可用于removeNodeInsertedListener()来移除监听；如果没有参数handler，则不返回任何值
 * 本函数要用到上边的addStyleCompatible函数
 * 本函数兼容：IE 10、Firefox 5+、Chrome 3+、Opera 12、Android 2.0+、Safari 4+、iPhone Safari，不支持IE9或以下
 * 注意：当函数添加动画CSS样式的时候，如果对象元素已载入，那么就会当即触发此动画，然后被当前的和之前的监听器监听到而执行处理函数，你可能需要在你的事件处理函数中判断一下这种情况。所以一般建议在对象元素未载入时使用本函数，或至少在其未载入时添加动画CSS样式，监听事件（而不添加动画，这样就不会触发动画，被监听到）可以放在其载入后

 * 范例：

//====普通添删监听====
var bindedFunc = addNodeInsertedListener("#myContainer .myDivs", function() {
alert(".myDivs is showing up!");
});
removeNodeInsertedListener(bindedFunc);

//====只在元素首次载入时执行（首次执行函数时移除监听）====
addNodeInsertedListener("#myContainer .myDivs", function() {
alert(".myDivs is showing up!");
}, true);

//====监听事件（多次），不添加动画CSS样式（当对象元素已经有动画CSS样式“animation-name”、“@keyframes”的时候）====
addNodeInsertedListener("#myContainer .myDivs", function() {
alert(".myDivs is showing up!");
}, false, true);

//====不监听事件，只添加动画CSS样式====
addNodeInsertedListener("#myContainer .myDivs");

 */
function addNodeInsertedListener(elCssPath, handler, executeOnce, noStyle) {
	var animName = "anilanim",
	prefixList = ["-o-", "-ms-", "-khtml-", "-moz-", "-webkit-", ""],
	eventTypeList = ["animationstart", "webkitAnimationStart", "MSAnimationStart", "oAnimationStart"],
	forEach = function (array, func) {
		for (var i = 0, l = array.length; i < l; i++) {
			func(array[i]);
		}
	};
	if (!noStyle) {
		var css = elCssPath + "{",
		css2 = "";
		forEach(prefixList, function (prefix) {
			css += prefix + "animation-duration:.001s;" + prefix + "animation-name:" + animName + ";";
			css2 += "@" + prefix + "keyframes " + animName + "{from{opacity:.9;}to{opacity:1;}}";
		});
		css += "}" + css2;
		addStyleCompatible(css);
	}
	if (handler) {
		var bindedFunc = function (e) {
			var els = document.querySelectorAll(elCssPath),
			tar = e.target,
			match = false;
			if (els.length !== 0) {
				forEach(els, function (el) {
					if (tar === el) {
						if (executeOnce) {
							removeNodeInsertedListener(bindedFunc);
						}
						handler.call(tar, e);
						return;
					}
				});
			}
		};
		forEach(eventTypeList, function (eventType) {
			document.addEventListener(eventType, bindedFunc, false);
		});
		return bindedFunc;
	}
}
/*
 * removeNodeInsertedListener函数
 * 本函数能移除addNodeInsertedListener函数绑定的监听
 * @参数bindedFunc：addNodeInsertedListener函数使用后的返回值，即其实际绑定的事件处理函数。
 */
function removeNodeInsertedListener(bindedFunc) {
	var eventTypeList = ["animationstart", "webkitAnimationStart", "MSAnimationStart", "oAnimationStart"],
	forEach = function (array, func) {
		for (var i = 0, l = array.length; i < l; i++) {
			func(array[i]);
		}
	};
	forEach(eventTypeList, function (eventType) {
		document.removeEventListener(eventType, bindedFunc, false);
	});
}
// 对Date的扩展，将 Date 转化为指定格式的String
// 月(M)、日(d)、小时(h)、分(m)、秒(s)、季度(q) 可以用 1-2 个占位符，
// 年(y)可以用 1-4 个占位符，毫秒(S)只能用 1 个占位符(是 1-3 位的数字)
// 例子：
// (new Date()).Format("yyyy-MM-dd hh:mm:ss.S") ==> 2006-07-02 08:09:04.423
// (new Date()).Format("yyyy-M-d h:m:s.S")      ==> 2006-7-2 8:9:4.18
Date.prototype.Format = function (fmt) { //author: meizz
	var o = {
		"M+" : this.getMonth() + 1, //月份
		"d+" : this.getDate(), //日
		"H+" : this.getHours(), //小时
		"m+" : this.getMinutes(), //分
		"s+" : this.getSeconds(), //秒
		"q+" : Math.floor((this.getMonth() + 3) / 3), //季度
		"S" : this.getMilliseconds() //毫秒
	};
	if (/(y+)/.test(fmt))
		fmt = fmt.replace(RegExp.$1, (this.getFullYear() + "").substr(4 - RegExp.$1.length));
	for (var k in o)
		if (new RegExp("(" + k + ")").test(fmt))
			fmt = fmt.replace(RegExp.$1, (RegExp.$1.length == 1) ? (o[k]) : (("00" + o[k]).substr(("" + o[k]).length)));
	return fmt;
}

var base64EncodeChars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
var base64DecodeChars = new Array(
		-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
		-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
		-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 62, -1, -1, -1, 63,
		52, 53, 54, 55, 56, 57, 58, 59, 60, 61, -1, -1, -1, -1, -1, -1,
		-1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
		15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, -1, -1, -1, -1, -1,
		-1, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
		41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, -1, -1, -1, -1, -1);
//base64编码
function base64_encode(str) {
	var out,
	i,
	len;
	var c1,
	c2,
	c3;

	len = str.length;
	i = 0;
	out = "";
	while (i < len) {
		c1 = str.charCodeAt(i++) & 0xff;
		if (i == len) {
			out += base64EncodeChars.charAt(c1 >> 2);
			out += base64EncodeChars.charAt((c1 & 0x3) << 4);
			out += "==";
			break;
		}
		c2 = str.charCodeAt(i++);
		if (i == len) {
			out += base64EncodeChars.charAt(c1 >> 2);
			out += base64EncodeChars.charAt(((c1 & 0x3) << 4) | ((c2 & 0xF0) >> 4));
			out += base64EncodeChars.charAt((c2 & 0xF) << 2);
			out += "=";
			break;
		}
		c3 = str.charCodeAt(i++);
		out += base64EncodeChars.charAt(c1 >> 2);
		out += base64EncodeChars.charAt(((c1 & 0x3) << 4) | ((c2 & 0xF0) >> 4));
		out += base64EncodeChars.charAt(((c2 & 0xF) << 2) | ((c3 & 0xC0) >> 6));
		out += base64EncodeChars.charAt(c3 & 0x3F);
	}
	return out;
}
//base64解码
function base64_decode(str) {
	var c1,
	c2,
	c3,
	c4;
	var i,
	len,
	out;

	len = str.length;
	i = 0;
	out = "";
	while (i < len) {
		/* c1 */
		do {
			c1 = base64DecodeChars[str.charCodeAt(i++) & 0xff];
		} while (i < len && c1 == -1);
		if (c1 == -1)
			break;

		/* c2 */
		do {
			c2 = base64DecodeChars[str.charCodeAt(i++) & 0xff];
		} while (i < len && c2 == -1);
		if (c2 == -1)
			break;

		out += String.fromCharCode((c1 << 2) | ((c2 & 0x30) >> 4));

		/* c3 */
		do {
			c3 = str.charCodeAt(i++) & 0xff;
			if (c3 == 61)
				return out;
			c3 = base64DecodeChars[c3];
		} while (i < len && c3 == -1);
		if (c3 == -1)
			break;

		out += String.fromCharCode(((c2 & 0XF) << 4) | ((c3 & 0x3C) >> 2));

		/* c4 */
		do {
			c4 = str.charCodeAt(i++) & 0xff;
			if (c4 == 61)
				return out;
			c4 = base64DecodeChars[c4];
		} while (i < len && c4 == -1);
		if (c4 == -1)
			break;
		out += String.fromCharCode(((c3 & 0x03) << 6) | c4);
	}
	return out;
}
//utf-8转utf16
function utf16to8(str) {
	var out,
	i,
	len,
	c;

	out = "";
	len = str.length;
	for (i = 0; i < len; i++) {
		c = str.charCodeAt(i);
		if ((c >= 0x0001) && (c <= 0x007F)) {
			out += str.charAt(i);
		} else if (c > 0x07FF) {
			out += String.fromCharCode(0xE0 | ((c >> 12) & 0x0F));
			out += String.fromCharCode(0x80 | ((c >> 6) & 0x3F));
			out += String.fromCharCode(0x80 | ((c >> 0) & 0x3F));
		} else {
			out += String.fromCharCode(0xC0 | ((c >> 6) & 0x1F));
			out += String.fromCharCode(0x80 | ((c >> 0) & 0x3F));
		}
	}
	return out;
}
//utf-16转utf-8
function utf8to16(str) {
	var out,
	i,
	len,
	c;
	var char2,
	char3;

	out = "";
	len = str.length;
	i = 0;
	while (i < len) {
		c = str.charCodeAt(i++);
		switch (c >> 4) {
		case 0:
		case 1:
		case 2:
		case 3:
		case 4:
		case 5:
		case 6:
		case 7:
			// 0xxxxxxx
			out += str.charAt(i - 1);
			break;
		case 12:
		case 13:
			// 110x xxxx   10xx xxxx
			char2 = str.charCodeAt(i++);
			out += String.fromCharCode(((c & 0x1F) << 6) | (char2 & 0x3F));
			break;
		case 14:
			// 1110 xxxx  10xx xxxx  10xx xxxx
			char2 = str.charCodeAt(i++);
			char3 = str.charCodeAt(i++);
			out += String.fromCharCode(((c & 0x0F) << 12) |
				((char2 & 0x3F) << 6) |
				((char3 & 0x3F) << 0));
			break;
		}
	}
	return out;
}
